﻿using Microsoft.Reporting.WebForms;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace EPlusReport
{
    public class RDLCReport
    {
        /// <summary>
        /// Generate RDLC
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="dt"></param>
        /// <param name="sTitle"></param>
        /// <param name="sSubTitle"></param>
        /// <param name="cols">column:width,column:width </param>
        public static void GenRDLC(string filename, DataTable dt, string sTitle, string sSubTitle, string cols)
        {
            string dsName = dt.TableName;
            RDLCGenerator gen = new RDLCGenerator(dt, dsName);
            
            gen.strsubTitle = sSubTitle;
            gen.strTitle = sTitle;
            gen.tablecols = cols;
            //ReportDataSource ds = new ReportDataSource(dsName, dt);
            MemoryStream sm = gen.GeneraReport();
            File.WriteAllBytes(filename, sm.ToArray());
        }

        /// <summary>
        /// Generate RDLC with ds
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="ds"></param>
        /// <param name="sTitle"></param>
        /// <param name="sSubTitle"></param>
        public static void GenRDLC(string filename, DataSet ds, string sTitle, string sSubTitle)
        {
            if (ds.Tables.Count == 0) return;

            string dsName = ds.Tables[0].TableName;
            RDLCGenerator gen = new RDLCGenerator(ds, dsName);
            gen.strsubTitle = sSubTitle;
            gen.strTitle = sTitle;
            //ReportDataSource ds = new ReportDataSource(dsName, dt);
            MemoryStream sm = gen.GeneraReport();
            File.WriteAllBytes(filename, sm.ToArray());
        }

        public static void BindWebRDLC(object dtAndds, string sReportPath, string sReportOutput, string para1)
        {
            if (!(dtAndds is DataTable || dtAndds is DataSet))
            {
                return;
            }
            LocalReport RVLocalReport = new LocalReport();
            bool eei = RVLocalReport.EnableExternalImages;
            bool eh = RVLocalReport.EnableHyperlinks;
            RVLocalReport.Refresh();
            RVLocalReport.EnableHyperlinks = eh;
            RVLocalReport.EnableExternalImages = eei;
            RVLocalReport.ReportPath = sReportPath;
            RVLocalReport.SubreportProcessing += new SubreportProcessingEventHandler(RVLocalReport_SubreportProcessing);
            if (dtAndds is DataTable)
            {
                DataTable dt = dtAndds as DataTable;
                RVLocalReport.DataSources.Add(new ReportDataSource(dt.TableName, dt));
            }
            else
            {
                DataSet ds = dtAndds as DataSet;
                foreach (DataTable dt in ds.Tables)
                {
                    RVLocalReport.DataSources.Add(new ReportDataSource(dt.TableName, dt));
                }
            }
            if (para1 != null)
            {

                System.Collections.Generic.List<ReportParameter> lstpara = new System.Collections.Generic.List<ReportParameter>();
                lstpara.Add(new ReportParameter("para1", para1));
                RVLocalReport.SetParameters(lstpara);
            }
            RVLocalReport.DisplayName = sReportOutput;
            RVLocalReport.Refresh();

            //string printer = pub.GetPara("printer");
            //if (!string.IsNullOrEmpty(printer))
            //{
            //    new ReportViewer_Stream_Print().PrintStream(RVLocalReport, printer);
            //    return;
            //}

            string fmt = "PDF";
            string ext = new FileInfo(sReportOutput).Extension.ToUpper().Trim('.');
            if (ext == "XLS") fmt = "EXCEL";
            if (ext == ".DOC") fmt = "WORD";
            if (!"PDF;XLS;DOC".Split(';').Contains(ext))
            {
                sReportOutput += ".PDF";
            }

            byte[] bytes = null;
            bytes = RVLocalReport.Render(fmt);

            string tmpfile = sReportOutput; //GetTempFileName(sReportName);
            using (FileStream fs = new FileStream(tmpfile, FileMode.Create))
            {
                fs.Write(bytes, 0, bytes.Length);
            }
        }

        static void RVLocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
        {
            LocalReport lr = (sender as LocalReport);
            for (int i = 0; i < lr.DataSources.Count; i++)
            {
                DataTable dt = lr.DataSources[i].Value as DataTable;
                e.DataSources.Add(new ReportDataSource(dt.TableName, dt));
            }
        }

    }

    /// <summary>
    /// Generate RDLC Report (*.RDLC) Version 2005 / 2008 
    /// </summary>
    class RDLCGenerator
    {
        //private float multipageRatio = 1.5F;
        private CultureInfo ci = new CultureInfo("en-US");
        private DataTable dt = null;
        private string dsName = "";
        private string nsRd = "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner";
        private string ns = "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition";
        public string strTitle = "";
        public string strsubTitle = "";
        private string sDataSource = "DataSource1";
        public List<DataTable> lstTables = new List<DataTable>();

        public RDLCGenerator(DataTable dt, string dsName)
        {
            this.dt = dt;
            this.dsName = dsName;
        }

        public RDLCGenerator(DataSet ds, string dsName)
        {
            this.dt = ds.Tables[0];
            this.dsName = dsName.Replace(" ", "_");
            for (int i = 1; i < ds.Tables.Count; i++)
            {
                lstTables.Add(ds.Tables[i]);
            }
        }

        //col_name:width
        public string tablecols = "";

        /// <summary>
        /// GeneraReport with cols
        /// </summary>
        /// <returns></returns>
        public MemoryStream GeneraReport()
        {
            this.dsName = dsName.Replace(" ", "_");

            string xml;
            StringBuilder sb = new StringBuilder();
            #region Settings
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.CheckCharacters = true;
            settings.CloseOutput = true;
            settings.Encoding = Encoding.UTF8;
            settings.Indent = true;
            settings.IndentChars = "\t";
            settings.NewLineChars = "\r\n";
            settings.NewLineHandling = NewLineHandling.Replace;
            settings.NewLineOnAttributes = false;
            settings.OmitXmlDeclaration = false;
            #endregion
            XmlWriter writer = XmlWriter.Create(sb, settings);
            writer.WriteStartDocument();
            {
                writer.WriteStartElement("Report", ns);
                writer.WriteAttributeString("xmlns", "rd", "", nsRd);
                {
                    AddDataSource(writer, sDataSource);
                    //write a para
                    writer.WriteStartElement("ReportParameters");
                    {
                        writer.WriteStartElement("ReportParameter");
                        {
                            writer.WriteAttributeString("Name", "para1");
                            writer.WriteElementString("DataType", "String");
                            writer.WriteElementString("Nullable", "true");
                            writer.WriteElementString("AllowBlank", "true");
                            writer.WriteElementString("Prompt", "Sub Title");
                        }
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                    writer.WriteRaw("<rd:GridSpacing>0.1cm</rd:GridSpacing>");

                    float htb = 0.63492F, maxWidth = 4.0F;
                    //RectangleF dimensioni = new RectangleF(1.37301F, 0.68783F, 13.25397F, 2.98941F);
                    float bodyWidth = GetTableWidth(this.dt, maxWidth);
                    RectangleF dimensioni = new RectangleF(0F, 0F, bodyWidth, 2F);
                    Padding pad = new Padding(1, 1, 1, 1);
                    SizeF size = new SizeF(21F, 29.7F);
                    if (bodyWidth > 21F)
                    {
                        size = new SizeF(29.7F, 21F);
                    }

                    Padding margin = new Padding(0.5F, 0.5F, 0.5F, 0.5F);
                    GenerateSettingsHeader(writer, size, size, margin);
                    writer.WriteElementString("Width", bodyWidth.ToString(ci) + "cm");

                    if (!string.IsNullOrEmpty(this.strTitle))
                    {
                        AddHeader(writer, pad);
                    }

                    writer.WriteStartElement("DataSets");
                    {
                        AddDataSet(writer, dt, dsName);
                        foreach (DataTable dt2 in lstTables)
                        {
                            AddDataSet(writer, dt2, dt2.TableName);
                        }
                    }
                    writer.WriteEndElement();

                    writer.WriteStartElement("Body");
                    {
                        writer.WriteElementString("ColumnSpacing", "0.5cm");
                        int iheight = (lstTables.Count + 1);
                        writer.WriteElementString("Height", string.Concat(iheight, "cm"));
                        writer.WriteStartElement("ReportItems");
                        {
                            GeneraTabella(writer, dt, dsName, dimensioni, pad, pad, htb, maxWidth);
                            for (int i = 0; i < lstTables.Count; i++)
                            {
                                dt = lstTables[i];
                                dsName = lstTables[i].TableName;
                                dimensioni = new RectangleF(0F, (i + 1) * 3F, bodyWidth, 2F);
                                GeneraTabella(writer, dt, dsName, dimensioni, pad, pad, htb, maxWidth);
                            }
                        }

                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
            xml = sb.ToString().Replace("utf-16", "utf-8");
            return new MemoryStream(Encoding.UTF8.GetBytes(xml));
        }

        #region Metodi Privati
        private SizeF GetDynamicSize(string s)
        {
            Font f = new Font(FontFamily.GenericSansSerif, 9);
            return GetDynamicSize(s, f);
        }

        private SizeF GetDynamicSize(string s, Font f)
        {
            Bitmap bmp = new Bitmap(1, 1);
            Graphics g = Graphics.FromImage(bmp);
            g.PageUnit = GraphicsUnit.Millimeter;
            SizeF ret = SizeF.Empty;
            ret = g.MeasureString(s, f);
            g.Dispose();
            return ret;
        }

        private void GeneraSezioneTabella(SezioneTabella sezione, XmlWriter writer, DataTable dt, Padding padding, float height)
        {
            string nomeSezione = "", templateValore = "", valore = "";
            CellColors colors = null;
            switch (sezione)
            {
                case SezioneTabella.Header:
                    {
                        nomeSezione = "Header";
                        templateValore = "{0}";
                        //colors = new CellColors(Color.Black, Color.White);
                        colors = new CellColors(Color.LightSteelBlue, Color.Black);
                        break;
                    }
                case SezioneTabella.Details:
                    {
                        nomeSezione = "Details";
                        templateValore = "=Fields!{0}.Value";
                        break;
                    }
                case SezioneTabella.Footer:
                    {
                        nomeSezione = "Footer";
                        templateValore = "{0}";
                        break;
                    }
            }
            writer.WriteStartElement(nomeSezione);
            {
                if (sezione == SezioneTabella.Header)
                    writer.WriteElementString("RepeatOnNewPage", "true");
                writer.WriteStartElement("TableRows");
                {
                    writer.WriteStartElement("TableRow");
                    {
                        writer.WriteElementString("Height", height.ToString(ci) + "cm");
                        writer.WriteStartElement("TableCells");
                        {
                            for (int i = 0; i < dt.Columns.Count; i++)
                            {
                                writer.WriteStartElement("TableCell");
                                {
                                    writer.WriteStartElement("ReportItems");
                                    {
                                        valore = String.Format(templateValore, dt.Columns[i].ColumnName.Replace(" ", "_"));
                                        GeneraTextBox(writer, string.Concat("textbox", iZIndex, nomeSezione, i), RectangleF.Empty, padding, colors, valore);
                                    }
                                    writer.WriteEndElement();
                                }
                                writer.WriteEndElement();

                            }
                        }
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        private float GetTableWidth(DataTable dt, float MaxWidth)
        {
            float bodyWidth = 1F;
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                DataColumn dc = dt.Columns[i];
                float sizeWidthComputed = 0.0F;
                float RowMaxLength = (GetDynamicSize(dc.ColumnName).Width / 10) + 0.2F;
                float HeaderMaxLength = RowMaxLength; // (GetDynamicSize(dc.ColumnName).Width / 10) + 0.2F;
                foreach (DataRow row in dt.Rows)
                {
                    float rowSizeWidth = GetDynamicSize(row[i].ToString()).Width / 10;
                    if (rowSizeWidth > RowMaxLength)
                        RowMaxLength = rowSizeWidth;
                }

                if (RowMaxLength > HeaderMaxLength)
                    if (RowMaxLength > MaxWidth)
                        sizeWidthComputed = MaxWidth;
                    else
                        sizeWidthComputed = RowMaxLength;
                else
                    sizeWidthComputed = HeaderMaxLength;

                bodyWidth += sizeWidthComputed;

            }
            return bodyWidth;
        }
        private int iZIndex = 1;

        System.Collections.Hashtable htcols = new System.Collections.Hashtable();

        private void GeneraTabella(XmlWriter writer, DataTable dt, string dsName, RectangleF dimensioniTabella, Padding paddingTextBox, Padding paddingHeader, float heightTextBox, float MaxWidth)
        {
            dsName = dsName.Replace(" ", "_");
            htcols.Clear();
            foreach (string s in string.Concat(tablecols).Split(','))
            {
                string[] ss = s.Split(':');
                if (ss.Length == 2)
                {
                    htcols.Add(ss[0].ToUpper(), ss[1]);
                }
            }

            writer.WriteStartElement("Table");

            writer.WriteAttributeString("Name", "tabella" + dsName);
            {
                writer.WriteElementString("ZIndex", iZIndex.ToString());
                iZIndex++;
                writer.WriteElementString("DataSetName", dsName);

                writer.WriteStartElement("Style");
                {
                    writer.WriteStartElement("BorderColor");
                    {
                        writer.WriteElementString("Default", "LightGrey");
                    }
                    writer.WriteEndElement();

                    writer.WriteStartElement("BorderStyle");
                    {
                        writer.WriteElementString("Default", "Solid");
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.WriteElementString("Top", dimensioniTabella.Top.ToString(ci) + "cm");
                writer.WriteElementString("Left", dimensioniTabella.Left.ToString(ci) + "cm");
                writer.WriteElementString("Width", dimensioniTabella.Width.ToString(ci) + "cm");
                writer.WriteElementString("Height", dimensioniTabella.Height.ToString(ci) + "cm");
                writer.WriteStartElement("TableColumns");
                {

                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        writer.WriteStartElement("TableColumn");
                        {
                            DataColumn dc = dt.Columns[i];
                            float sizeWidthComputed = 0.0F;
                            float HeaderMaxLength = (GetDynamicSize(dc.ColumnName).Width / 10) + 0.2F;
                            if (htcols.Contains(dc.ColumnName.ToUpper()))
                                float.TryParse(htcols[dc.ColumnName.ToUpper()].ToString(), out HeaderMaxLength);

                            sizeWidthComputed = HeaderMaxLength;

                            //float RowMaxLength = 21 / dt.Columns.Count;
                            //float RowMaxLength = HeaderMaxLength;
                            //foreach (DataRow row in dt.Rows)
                            //{
                            //    float rowSizeWidth = GetDynamicSize(row[i].ToString()).Width / 10;
                            //    if (rowSizeWidth > RowMaxLength)
                            //        RowMaxLength = rowSizeWidth;
                            //}
                            //if (RowMaxLength > HeaderMaxLength)
                            //    if (RowMaxLength > MaxWidth)
                            //        sizeWidthComputed = MaxWidth;
                            //    else
                            //        sizeWidthComputed = RowMaxLength;
                            //else
                            //    sizeWidthComputed = HeaderMaxLength;

                            writer.WriteElementString("Width", (sizeWidthComputed).ToString(ci) + "cm");
                        }
                        writer.WriteEndElement();
                    }
                }
                writer.WriteEndElement();
                GeneraSezioneTabella(SezioneTabella.Header, writer, dt, paddingHeader, heightTextBox);
                GeneraSezioneTabella(SezioneTabella.Details, writer, dt, paddingTextBox, heightTextBox);
                //GeneraSezioneTabella(SezioneTabella.Footer, writer, dt, paddingHeader, heightTextBox);

            }
            writer.WriteEndElement();
        }


        private void AddHeader(XmlWriter writer, Padding padding)
        {
            writer.WriteStartElement("PageHeader");
            {
                float ftop = 0.2F;
                writer.WriteElementString("PrintOnFirstPage", "true");
                writer.WriteStartElement("ReportItems");
                {
                    Font f = new Font("SimSun", 12F, FontStyle.Bold);
                    float HeaderMaxLength = (GetDynamicSize(strTitle, f).Height / 10);
                    if (HeaderMaxLength < 0.5F) HeaderMaxLength = 0.5F;

                    GeneraTextBox(writer, "txtTitle", new RectangleF(0.25F, ftop, 21F, HeaderMaxLength), padding, null, this.strTitle, f, BorderStyle.None);
                    ftop += 2 * HeaderMaxLength;
                    //
                    f = new Font("SimSun", 9F);
                    HeaderMaxLength = (GetDynamicSize(strsubTitle, f).Height / 10);
                    if (HeaderMaxLength < 0.5F) HeaderMaxLength = 0.5F;
                    GeneraTextBox(writer, "txtsubTitle", new RectangleF(0.25F, ftop, 21F, HeaderMaxLength), null, null, "=Parameters!para1.Value", f, BorderStyle.None);
                }
                writer.WriteEndElement();
                //ftop += 1F;
                writer.WriteElementString("Height", ftop.ToString(ci) + "cm");
                writer.WriteElementString("PrintOnLastPage", "true");
            }
            writer.WriteEndElement();
        }

        private void AddDataSet(XmlWriter writer, DataTable dt, string dsName)
        {
            writer.WriteStartElement("DataSet");
            writer.WriteAttributeString("Name", dsName.Replace(" ", "_"));
            {
                writer.WriteStartElement("Fields");
                {
                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        writer.WriteStartElement("Field");
                        writer.WriteAttributeString("Name", dt.Columns[i].ColumnName.Replace(" ", "_"));
                        {
                            writer.WriteElementString("DataField", dt.Columns[i].ColumnName);
                            writer.WriteElementString("rd", "TypeName", nsRd, dt.Columns[i].DataType.ToString());
                        }
                        writer.WriteEndElement();
                    }
                }
                writer.WriteEndElement();

                writer.WriteStartElement("Query");
                {
                    writer.WriteElementString("DataSourceName", sDataSource);
                    writer.WriteElementString("CommandText", "");
                    writer.WriteElementString("rd", "DataSourceName", nsRd, "true");
                }
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        private void AddDataSource(XmlWriter writer, string dsName)
        {
            writer.WriteStartElement("DataSources");
            {
                writer.WriteStartElement("DataSource");
                {
                    writer.WriteAttributeString("Name", dsName.Replace(" ", "_"));
                    writer.WriteElementString("DataSourceReference", dsName.Replace(" ", "_"));
                }
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        private void GeneraTextBox(XmlWriter writer, string textboxName, RectangleF dimensioni, Padding padding, CellColors colors, string value)
        {
            GeneraTextBox(writer, textboxName, dimensioni, padding, colors, value, null, BorderStyle.Solid);
        }

        private void GeneraTextBox(XmlWriter writer, string textboxName, RectangleF dimensioni, Padding padding, CellColors colors, string value, Font font, BorderStyle border)
        {
            writer.WriteStartElement("Textbox");
            writer.WriteAttributeString("Name", textboxName);
            {
                writer.WriteElementString("rd", "DefaultName", nsRd, textboxName);
                if (dimensioni != RectangleF.Empty)
                {
                    writer.WriteElementString("Top", dimensioni.Top.ToString(ci) + "cm");
                    writer.WriteElementString("Left", dimensioni.Left.ToString(ci) + "cm");
                    writer.WriteElementString("Width", dimensioni.Width.ToString(ci) + "cm");
                    writer.WriteElementString("Height", dimensioni.Height.ToString(ci) + "cm");
                }
                writer.WriteElementString("CanGrow", "true");
                writer.WriteElementString("Value", value);
                if (padding != null)
                {
                    writer.WriteStartElement("Style");
                    {
                        if (border == BorderStyle.Solid)
                        {
                            writer.WriteStartElement("BorderColor");
                            {
                                writer.WriteElementString("Default", "Gainsboro");
                            }
                            writer.WriteEndElement();
                        }

                        writer.WriteStartElement("BorderStyle");
                        {
                            //writer.WriteElementString("Default", "Solid");
                            writer.WriteElementString("Default", Enum.GetName(border.GetType(), border));
                        }
                        writer.WriteEndElement();

                        if (colors != null)
                        {
                            writer.WriteElementString("Color", colors.ForegroundColor.Name);
                            writer.WriteElementString("BackgroundColor", colors.BackgroundColor.Name);
                        }
                        if (font != null)
                        {
                            writer.WriteElementString("FontFamily", font.Name);
                            writer.WriteElementString("FontSize", font.Size.ToString(ci) + "pt");
                            if (font.Bold)
                            {
                                writer.WriteElementString("FontWeight", "700");
                            }
                        }
                        writer.WriteElementString("PaddingLeft", padding.Left.ToString(ci) + "pt");
                        writer.WriteElementString("PaddingRight", padding.Right.ToString(ci) + "pt");
                        writer.WriteElementString("PaddingTop", padding.Top.ToString(ci) + "pt");
                        writer.WriteElementString("PaddingBottom", padding.Bottom.ToString(ci) + "pt");
                    }
                    writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
        }

        private void GenerateSettingsHeader(XmlWriter writer, SizeF InteractiveSize, SizeF PageSize, Padding margin)
        {
            //writer.WriteElementString("Language", "it-IT");
            writer.WriteElementString("rd", "DrawGrid", nsRd, "true");
            writer.WriteElementString("rd", "gridspacing", nsRd, "0.1cm");
            writer.WriteElementString("rd", "snaptogrid", nsRd, "true");
            writer.WriteElementString("InteractiveHeight", InteractiveSize.Height.ToString(ci) + "cm");
            writer.WriteElementString("InteractiveWidth", InteractiveSize.Width.ToString(ci) + "cm");
            writer.WriteElementString("RightMargin", margin.Right.ToString(ci) + "cm");
            writer.WriteElementString("LeftMargin", margin.Left.ToString(ci) + "cm");
            writer.WriteElementString("BottomMargin", margin.Bottom.ToString(ci) + "cm");
            writer.WriteElementString("TopMargin", margin.Top.ToString(ci) + "cm");
            writer.WriteElementString("PageHeight", PageSize.Height.ToString(ci) + "cm");
            writer.WriteElementString("PageWidth", PageSize.Width.ToString(ci) + "cm");
        }
        #endregion

        /*
        /// <summary>
        /// 
        /// </summary>
        /// <param name="RV"></param>
        /// <param name="dt"></param>
        public static void BindRDLC(ReportViewer RV, DataTable dt)
        {
            string dsName = dt.TableName;
            ReportGenerator gen = new ReportGenerator(dt, dsName);
            ReportDataSource ds = new ReportDataSource(dsName, dt);
            RV.Reset();
            RV.LocalReport.DataSources.Add(ds);
            RV.LocalReport.DisplayName = dsName;
            RV.LocalReport.LoadReportDefinition(gen.GeneraReport());
        }

        public static void BindRDLC(string sReport,DataTable dt,string outfile)
        {
            string dsName = dt.TableName;
            ReportGenerator gen = new ReportGenerator(dt, dsName);
            ReportDataSource ds = new ReportDataSource(dsName, dt);
            LocalReport LR = new LocalReport();
            LR.DataSources.Add(ds);
            LR.DisplayName = dsName;
            LR.ReportPath = sReport;
            LR.Refresh();
            string encoding="";
            string mimetype="";
            string sext="";
            string deviceinfo = "";
            string[] streams=null;
            Warning[] warms=null;

            string format = "PDF";
            if (outfile.Substring(outfile.LastIndexOf('.')).ToLower() == ".xls")
            {
                format = "EXCEL";
            }
            byte[] data = LR.Render(format,deviceinfo,out mimetype, out encoding, out sext, out streams,out warms);
            if (File.Exists(outfile))
                File.Delete(outfile);
            File.WriteAllBytes(outfile, data);
        }

        /// <summary>
        /// WinForm Show
        /// </summary>
        /// <param name="RV"></param>
        /// <param name="dt"></param>
        public static void BindRDLC(string sReport, DataTable dt, bool isShow)
        {
            string dsName = dt.TableName;
            System.Windows.Forms.Form fmReportView = new System.Windows.Forms.Form();
            fmReportView.Show();
            ReportViewer RV = new ReportViewer();
            fmReportView.Controls.Add(RV);
            RV.Dock = System.Windows.Forms.DockStyle.Fill;
            ReportGenerator gen = new ReportGenerator(dt, dsName);
            ReportDataSource ds = new ReportDataSource(dsName, dt);
            RV.Reset();
            RV.LocalReport.DataSources.Add(ds);
            RV.LocalReport.DisplayName = dsName;
            RV.LocalReport.ReportPath = sReport;
            RV.RefreshReport();
            fmReportView.Show();
            if (isShow)
            {
                fmReportView.Hide();
                fmReportView.WindowState = System.Windows.Forms.FormWindowState.Maximized;
                fmReportView.ShowDialog();
            }
            else
            {
                new ReportViewer_Stream_Print().PrintStream(RV.LocalReport);
                fmReportView.Dispose();
            }
        }

        /*
        public void BindRDLC(ReportViewer RV, DataSet dsData, string sReportPath,string sReportName, string para1)
        {
            if (dsData.Tables.Count == 0) return;

            string dsName = dsData.Tables[0].TableName;
            RV.Reset();
            RV.LocalReport.ReportPath = sReportPath; // .LoadReportDefinition(gen.GeneraReport());
            foreach (DataTable dt in dsData.Tables)
            {
                RV.LocalReport.DataSources.Add(new ReportDataSource(dt.TableName, dt));
            }
           
            if (para1 != null)
            {
                List<ReportParameter> lstpara = new List<ReportParameter>();
                lstpara.Add(new ReportParameter("para1",para1));
                RV.LocalReport.SetParameters(lstpara);
            }
            RV.LocalReport.DisplayName = sReportName;
            RV.RefreshReport();
        }
        */

        /// <summary>
        /// Generate RDLC
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="dt"></param>
        public static void GenRDLC(string filename, DataTable dt)
        {
            GenRDLC(filename, dt, null, null);
        }


        public static void GenRDLC(string filename, DataTable dt, string cols)
        {
            GenRDLC(filename, dt, null, null, cols);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="dt"></param>
        /// <param name="sTitle"></param>
        /// <param name="sSubTitle"></param>
        public static void GenRDLC(string filename, DataTable dt, string sTitle, string sSubTitle)
        {
            GenRDLC(filename, dt, sTitle, sSubTitle, null);
        }

        /// <summary>
        /// Generate RDLC
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="dt"></param>
        /// <param name="sTitle"></param>
        /// <param name="sSubTitle"></param>
        /// <param name="cols">column:width,column:width </param>
        public static void GenRDLC(string filename, DataTable dt, string sTitle, string sSubTitle, string cols)
        {
            string dsName = dt.TableName;
            RDLCGenerator gen = new RDLCGenerator(dt, dsName);
            gen.strsubTitle = sSubTitle;
            gen.strTitle = sTitle;
            gen.tablecols = cols;
            //ReportDataSource ds = new ReportDataSource(dsName, dt);
            MemoryStream sm = gen.GeneraReport();
            File.WriteAllBytes(filename, sm.ToArray());
        }


        /// <summary>
        /// Generate RDLC with ds
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="ds"></param>
        /// <param name="sTitle"></param>
        /// <param name="sSubTitle"></param>
        public static void GenRDLC(string filename, DataSet ds, string sTitle, string sSubTitle)
        {
            if (ds.Tables.Count == 0) return;

            string dsName = ds.Tables[0].TableName;
            RDLCGenerator gen = new RDLCGenerator(ds, dsName);
            gen.strsubTitle = sSubTitle;
            gen.strTitle = sTitle;
            //ReportDataSource ds = new ReportDataSource(dsName, dt);
            MemoryStream sm = gen.GeneraReport();
            File.WriteAllBytes(filename, sm.ToArray());
        }

    }

    #region Oggetti Custom
    public enum SezioneTabella
    {
        Header,
        Details,
        Footer
    }

    public class CellColors
    {
        public CellColors(Color bg, Color fore)
        {
            this.bg = bg;
            this.fore = fore;
        }
        private Color bg = Color.Empty;
        private Color fore = Color.Empty;

        public Color BackgroundColor { get { return bg; } }
        public Color ForegroundColor { get { return fore; } }
    }

    public class Padding
    {
        public Padding(float Top, float Left, float Bottom, float Right)
        {
            TopLeft = new PointF(Left, Top);
            BottomRight = new PointF(Right, Bottom);
        }

        private PointF TopLeft;

        private PointF BottomRight;

        public float Top { get { return TopLeft.Y; } }
        public float Left { get { return TopLeft.X; } }
        public float Bottom { get { return BottomRight.Y; } }
        public float Right { get { return BottomRight.X; } }
    }
    #endregion

    /*
    public class ReportViewer_Stream_Print : IDisposable
    {
        /// <summary>
        /// 用来记录当前打印到第几页了
        /// </summary>
        private int m_currentPageIndex;

        /// <summary>
        /// 声明一个Stream对象的列表用来保存报表的输出数据,LocalReport对象的Render方法会将报表按页输出为多个Stream对象。
        /// </summary>
        private IList<Stream> m_streams;

        private bool isLandSapces = false;

        /// <summary>
        /// 用来提供Stream对象的函数，用于LocalReport对象的Render方法的第三个参数。
        /// </summary>
        /// <param name="name"></param>
        /// <param name="fileNameExtension"></param>
        /// <param name="encoding"></param>
        /// <param name="mimeType"></param>
        /// <param name="willSeek"></param>
        /// <returns></returns>
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
        {
            //如果需要将报表输出的数据保存为文件，请使用FileStream对象。
            Stream stream = new MemoryStream();
            m_streams.Add(stream);
            return stream;
        }

        ReportPageSettings rps = null;
        /// <summary>
        /// 为Report.rdlc创建本地报告加载数据,输出报告到.emf文件,并打印,同时释放资源
        /// </summary>
        /// <param name="rv">参数:ReportViewer.LocalReport</param>
        public void PrintStream(LocalReport rvDoc)
        {
            //获取LocalReport中的报表页面方向
            isLandSapces = rvDoc.GetDefaultPageSettings().PaperSize.Width>900; //.IsLandscape;
            //System.Windows.Forms.MessageBox.Show(string.Concat("W:",rvDoc.GetDefaultPageSettings().PaperSize.Width," H:", rvDoc.GetDefaultPageSettings().PaperSize.Height));
            rps = rvDoc.GetDefaultPageSettings();
            Export(rvDoc);
            PrintSetting();
            Dispose();
        }

        private void Export(LocalReport report)
        {
            string deviceInfo =
            @"<DeviceInfo>
                 <OutputFormat>EMF</OutputFormat>
             </DeviceInfo>";
            Warning[] warnings;
            m_streams = new List<Stream>();
            //将报表的内容按照deviceInfo指定的格式输出到CreateStream函数提供的Stream中。
            report.Render("Image", deviceInfo, CreateStream, out warnings);
            foreach (Stream stream in m_streams)
                stream.Position = 0;
        }

        private void PrintSetting()
        {
            if (m_streams == null || m_streams.Count == 0)
                throw new Exception("错误:没有检测到打印数据流");
            //声明PrintDocument对象用于数据的打印
            PrintDocument printDoc = new PrintDocument();
            //判断指定的打印机是否可用
            if (!printDoc.PrinterSettings.IsValid)
            {
                throw new Exception("错误:找不到打印机");
            }
            else
            {
                //设置打印机方向遵从报表方向
                printDoc.DefaultPageSettings.PaperSize = rps.PaperSize;
                printDoc.DefaultPageSettings.Margins = rps.Margins;
                //printDoc.DefaultPageSettings.Landscape = isLandSapces;

                //声明PrintDocument对象的PrintPage事件，具体的打印操作需要在这个事件中处理。
                printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                m_currentPageIndex = 0;
                //执行打印操作，Print方法将触发PrintPage事件。
                printDoc.Print();
            }
        }

        /// <summary>
        /// 处理程序PrintPageEvents
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="ev"></param>
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            //Metafile对象用来保存EMF或WMF格式的图形，
            //我们在前面将报表的内容输出为EMF图形格式的数据流。
            Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);

            //调整打印机区域的边距
            Rectangle adjustedRect = new Rectangle(
                ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
                ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
                ev.PageBounds.Width,
                ev.PageBounds.Height);

            //绘制一个白色背景的报告
            //ev.Graphics.FillRectangle(Brushes.White, adjustedRect);

            //获取报告内容
            //这里的Graphics对象实际指向了打印机
            ev.Graphics.DrawImage(pageImage, adjustedRect);
            //ev.Graphics.DrawImage(pageImage, ev.PageBounds);

            // 准备下一个页,已确定操作尚未结束
            m_currentPageIndex++;

            //设置是否需要继续打印
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
        }

        public void Dispose()
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }
    }
    */

}
